﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using NLog;
using planerka.DataAccess.DataService;
using planerka.DataAccess.Models;
using planerka.Common;
using planerka.DataAccess.ViewModels;
using System.IO;
using Ionic.Zip;

namespace planerka.Web.Controllers
{
    public class AdminController : Controller
    {
        private static Logger logger = LogManager.GetCurrentClassLogger();

        // когда заходим в админку - сразу попадаем сюда
        [Authorize(Roles = "Administrator, Operator")]
        public ActionResult Index()
        {
            page mp = new _Repository<page>().All().Where(p => p.URL == "instruction" && p.pageCategory.tag == "instructions").FirstOrDefault();
            ViewData["content"] = mp != null ? mp.HTML_text : "Создайте категорию с тэгом 'instructions', в категорию поместите страницу с ЧПУ 'instruction'. Эту страницу используйте для формирования инструкции к программе";
            return View();
        }

        // управление категориями страниц
        #region managePageCategories

        // GET: /Admin/managePageCategories
        [Authorize(Roles = "Administrator")]
        [HttpGet]
        public ActionResult managePageCategories(int? id)
        {
            // Если ни одна категория не выбрана - возвращает id == 0

            pageAndPageCategoriesViewModel pcVM = new pageAndPageCategoriesViewModel();

            pcVM.selectedPageCategory = new _Repository<pageCategory>().All().Where(p => p.ID == id).FirstOrDefault();

            List<pageCategoryRoute> pageCatRoutes = pageCategory.retRoute(pcVM.selectedPageCategory);
            pageCatRoutes = pageCatRoutes.OrderBy(p => p.pageCategoryRouteValue).ToList();
            pageCatRoutes.Insert(0, new pageCategoryRoute { id = null, pageCategoryRouteValue = " --- top level" });
            ViewData["pageCategories"] = pageCatRoutes;
            return View(pcVM);
        }


        // POST: /Admin/managePageCategories
        [Authorize(Roles = "Administrator")]
        [HttpPost]
        [ValidateInput(false)]
        public ActionResult managePageCategories(int id, FormCollection formValues, string confirmButton)
        {
            pageAndPageCategoriesViewModel pcVM = new pageAndPageCategoriesViewModel();
            _Repository<pageCategory> pcRep = new _Repository<pageCategory>();

            if (confirmButton == "Сохранить")
            {
                #region
                if (id != 0)
                {
                    pageCategory pc = pcRep.All().Where(p => p.ID == id).First();

                    pcVM.selectedPageCategory = pc;

                    try
                    {
                        UpdateModel(pcVM);
                        pcRep.Save();
                    }
                    catch (Exception ex)
                    {

                        ExceptionUtility.LogException(logger, ex,
                        "public ActionResult managePageCategories()",
                        "ошибка сохранения");

                        // redisplay with errors
                        List<pageCategoryRoute> pageCatRoutes = pageCategory.retRoute(pcVM.selectedPageCategory);
                        pageCatRoutes = pageCatRoutes.OrderBy(p => p.pageCategoryRouteValue).ToList();
                        pageCatRoutes.Insert(0, new pageCategoryRoute { id = null, pageCategoryRouteValue = " --- top level" });
                        ViewData["pageCategories"] = pageCatRoutes;
                        return View(pcVM);

                    }
                }

                #endregion
            }
            else if (confirmButton == "Добавить новую категорию")
            {
                #region
                pageCategory pc = new pageCategory();
                string name = "НОВАЯ КАТЕГОРИЯ"; 
                string tag = "newCategory"; 

                if (name == "")
                    name = null;

                if (tag == "")
                    tag = null;

                pc.name = name;
                pc.tag = tag;
                pc.order = 0;
                pc.parent_ID = null;
                pcRep.InsertInstance(pc);

                try
                {
                    pcRep.Save();
                }
                catch (Exception ex)
                {
                    ExceptionUtility.LogException(logger, ex,
                        "public ActionResult managePageCategories(int id, FormCollection formValues, string confirmButton)",
                        "ошибка добавления категории страницы");

                    // redisplay with errors
                    pcVM.selectedPageCategory = pc;
                    return View(pcVM);
                }
                #endregion
            }
            else if (confirmButton == "Удалить")
            {
                #region
                pageCategory pc = pcRep.All().Where(p => p.ID == id).First();
                pcRep.MarkForDeletion(pc);


                try
                {

                    pcRep.Save();
                    ViewData["resultMessage"] = "Категория удалена успешно";
                }
                catch (Exception ex)
                {
                    ViewData["resultMessage"] = "Ошибка удаления категории. Возможно имеются связанные элементы";
                    // redisplay with errors
                    pcVM.selectedPageCategory = pc;

                    ExceptionUtility.LogException(logger, ex,
                        "public ActionResult managePageCategories(int id, FormCollection formValues, string confirmButton)",
                        "Ошибка удаления категории страницы");

                    List<pageCategoryRoute> pageCatRoutes = pageCategory.retRoute(pcVM.selectedPageCategory);
                    pageCatRoutes = pageCatRoutes.OrderBy(p => p.pageCategoryRouteValue).ToList();
                    pageCatRoutes.Insert(0, new pageCategoryRoute { id = null, pageCategoryRouteValue = " --- top level" });
                    ViewData["pageCategories"] = pageCatRoutes;

                    return View(pcVM);
                }

                #endregion
            }
            else if (confirmButton == "Up" || confirmButton == "Down")
            {
                #region
                pageCategory pc = pcRep.All().Where(p => p.ID == id).FirstOrDefault();

                if (pc == null)
                {
                    TempData["resultMessage"] = "Не выбрана категория";
                }
                else
                {
                    int delta = confirmButton == "Up" ? -1 : 1;
                    pc.move(delta);
                    return RedirectToAction("managePageCategories", new { id = id });
                }
                #endregion
            }

            return RedirectToAction("managePageCategories", new { id = id });
        }

        #endregion

        // управление страницами
        #region ManagePages

        // ===================================================================
        // ===================== ManagePages =================================
        // ===================================================================

        // GET: /Admin/ManagePages
        [Authorize(Roles = "Administrator")]
        public ActionResult ManagePages(int? id)
        {
            // Если id == 0, то следует выбрать самую первую страницу

            List<pageCategoryRoute> pageCatRoutes = pageCategory.retRoute(null);
            page selectedPage = null;
            // Если контроллер вызывается без параметров, то берем первую попавшуюся страницу
            if ((id == null) || (id == 0))
            {
                //selectedPage = db.pages.FirstOrDefault();
                selectedPage = new _Repository<page>().All().FirstOrDefault();

                if (selectedPage == null)
                {
                    selectedPage = new page();
                    TempData["resMessage"] = "Создайте новую страницу";
                }
            }
            else
                selectedPage = new _Repository<page>().All().Where(p => p.ID == id).FirstOrDefault();

            ViewData["pictureWidth"] = Convert.ToInt32(System.Configuration.ConfigurationManager.AppSettings["thumbnailsWidthForTabs"]);
            ViewData["resultMessage"] = TempData["resMessage"] != null ? TempData["resMessage"].ToString() : "";
            TempData["resMessage"] = null;

            ViewData["pageCategories"] = pageCatRoutes.OrderBy(p => p.pageCategoryRouteValue).ToList();
            pageAndPageCategoriesViewModel ptVM = new pageAndPageCategoriesViewModel
            {
                CurrentPage = selectedPage
            };

            if (TempData["headerError"] != null)
                ModelState.AddModelError("header", TempData["headerError"].ToString());


            return View(ptVM);
        }


        // POST: /ManagePages
        [Authorize(Roles = "Administrator")]
        [HttpPost]
        [ValidateInput(false)]
        public ActionResult ManagePages(int id, FormCollection formValues, string confirmButton)
        {
            _Repository<page> pageRepo = new _Repository<page>();
            if ((confirmButton == "Сохранить страницу") || (confirmButton == "загрузить картинку")
                 || (confirmButton == "загрузить видео") || (confirmButton == "загрузить презентацию"))
            {
                if (formValues["header"].ToString() == "")
                    TempData["headerError"] = "Поле 'заголовок' не заполнено";

                //
                if (!ModelState.IsValid)
                {
                    TempData["resMessage"] = "Пожалуйста, проверьте правильность заполнения";
                    return RedirectToAction("ManagePages", new { id = id });

                }

                //
                try
                {
                    page editedPage = pageRepo.All().Where(p => p.ID == id).FirstOrDefault();

                    editedPage.HTML_text = formValues["HtmlContent"].ToString();
                    editedPage.header = formValues["header"].ToString();

                    DateTime date = DateTime.Now;
                    try { date = Convert.ToDateTime(formValues["date"]); }
                    catch { }
                    editedPage.date = date;
                    editedPage.category_ID = Convert.ToInt32(formValues["pageCategoriesDD"]);
                    editedPage.HTML_announce = formValues["announce"].ToString();

                    editedPage.URL = formValues["URL"].ToString();
                    if (editedPage.URL == "")
                    {
                        translit tr = new translit();
                        editedPage.URL = tr.makeTranslitName(editedPage.header);
                    }

                    editedPage.metaDescription = formValues["metaDescription"].ToString();
                    editedPage.metaKeywords = formValues["metaKeywords"].ToString();
                    editedPage.metaTitle = formValues["metaTitle"].ToString();
                    pageRepo.Save();
                    TempData["resMessage"] = "Запись успешно сохранена";
                }
                catch (Exception ex)
                {
                    ExceptionUtility.LogException(logger, ex,
                        "public ActionResult ManagePages(int id, FormCollection formValues, string confirmButton)",
                        "Ошибка сохранения записи");

                    TempData["resMessage"] = "Ошибка сохранения записи";

                }

                return RedirectToAction("ManagePages", new { id = id });
            }
            else if (confirmButton == "Добавить страницу")
            {
                try
                {
                    page newPage = new page();

                    pageCategory pgc = new _Repository<pageCategory>().All().FirstOrDefault();
                    if (pgc == null)
                    {
                        TempData["resMessage"] = "Сначала создайте хотя бы одну категорию страниц";
                        return RedirectToAction("ManagePages", new { id = 0 });
                    }
                    newPage.category_ID = pgc.ID;
                    newPage.header = "Новая страница ...";
                    id = new _Repository<page>().All().Count();

                    newPage.order = id;
                    newPage.date = DateTime.Now;

                    pageRepo.InsertInstance(newPage);
                    pageRepo.Save();

                    id = new _Repository<page>().All().Max(p => p.ID); // id только что добавленной записи
                    TempData["resMessage"] = "Запись успешно добавлена";
                }
                catch (Exception ex)
                {
                    ExceptionUtility.LogException(logger, ex,
                        "public ActionResult ManagePages(int id, FormCollection formValues, string confirmButton)",
                        "Ошибка добавления страницы");

                }

                return RedirectToAction("ManagePages", new { id = id });
            }
            else if (confirmButton == "Удалить страницу")
            {

                try
                {
                    page deletedPage = pageRepo.All().Where(p => p.ID == id).FirstOrDefault();
                    pageRepo.MarkForDeletion(deletedPage);
                    pageRepo.Save();
                    TempData["resMessage"] = "Запись успешно удалена";
                }
                catch (Exception ex)
                {
                    TempData["resMessage"] = "Ошибка удаления страницы";

                    ExceptionUtility.LogException(logger, ex,
                        "public ActionResult ManagePages(int id, FormCollection formValues, string confirmButton)",
                        "Ошибка удаления страницы");

                }

                return RedirectToAction("ManagePages", new { id = 0 });

            }
            else if (confirmButton == "Up")
            {
                page movedPage = new _Repository<page>().All().Where(p => p.ID == id).FirstOrDefault();
                movedPage.move(-1);
                return RedirectToAction("ManagePages", new { id = id });
            }
            else if (confirmButton == "Down")
            {
                page movedPage = new _Repository<page>().All().Where(p => p.ID == id).FirstOrDefault();
                movedPage.move(1);
                return RedirectToAction("ManagePages", new { id = id });

            }
            else
                return RedirectToAction("ManagePages", new { id = id });
        }

        #endregion

        // журнал событий (ошибок)
        #region logs

        [Authorize(Roles = "Administrator")]
        [HttpGet]
        public ActionResult errorLog()
        {
            // Получить список  short log-файлов
            string directory = System.Web.HttpContext.Current.Server.MapPath("~/Logs/short/");
            System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(directory);
            // Get a reference to each file in that directory.
            System.IO.FileInfo[] fiArr = di.GetFiles();

            List<string> filesShort = new List<string>();
            double totalMBshortFiles = 0;
            foreach (System.IO.FileInfo finfo in fiArr)
            {
                filesShort.Add(finfo.Name);
                totalMBshortFiles += ((double)finfo.Length / (1024 * 1024));
            }

            ViewData["filesShort"] = filesShort;
            ViewData["totalMBshortFiles"] = totalMBshortFiles;

            ////////////////////////////////////////////////////////////////////////////

            directory = System.Web.HttpContext.Current.Server.MapPath("~/Logs/long/");
            di = new System.IO.DirectoryInfo(directory);

            fiArr = di.GetFiles();

            List<string> filesLong = new List<string>();
            double totalMBlongFiles = 0;
            foreach (System.IO.FileInfo finfo in fiArr)
            {
                filesLong.Add(finfo.Name);
                totalMBlongFiles += ((double)finfo.Length / (1024 * 1024));
            }

            ViewData["filesLong"] = filesLong;
            ViewData["totalMBlongFiles"] = totalMBlongFiles;

            ////////////////////////////////////////////////////////////////////////////

            return View();
        }

        // журнал ошибок - POST
        [Authorize(Roles = "Administrator")]
        [HttpPost]
        public ActionResult errorLog(string confirmButton)
        {
            if (confirmButton == "Очистить журнал")
            {

                string directory = System.Web.HttpContext.Current.Server.MapPath("~/Logs/short/");
                System.IO.DirectoryInfo di = new System.IO.DirectoryInfo(directory);
                // Get a reference to each file in that directory.
                System.IO.FileInfo[] fiArr = di.GetFiles();

                foreach (System.IO.FileInfo finfo in fiArr)
                {
                    System.IO.File.Delete(finfo.FullName);
                }

                directory = System.Web.HttpContext.Current.Server.MapPath("~/Logs/long/");
                di = new System.IO.DirectoryInfo(directory);
                // Get a reference to each file in that directory.
                fiArr = di.GetFiles();

                foreach (System.IO.FileInfo finfo in fiArr)
                {
                    System.IO.File.Delete(finfo.FullName);
                }

            }

            return RedirectToAction("errorLog");
        }

        #endregion 

        // служебные функции
        #region services

        //
        [Authorize(Roles = "Administrator")]
        [HttpGet]
        public ActionResult service()
        {
            return View();
        }

        [Authorize(Roles = "Administrator")]
        [HttpPost]
        public ActionResult service(FormCollection formValues, string confirmButton)
        {
            if (confirmButton == "Разархивировать файл")
            {
                #region

                string fname = formValues["fname"].ToString();
                if (fname.Trim() == "")
                {
                    ViewData["resultMessage"] = "Задайте имя файла";
                }
                else
                {
                    if (System.IO.File.Exists(Server.MapPath("~/" + fname.Trim())))
                    {
                        try
                        {
                            using (ZipFile zip = ZipFile.Read(Server.MapPath("~/" + fname.Trim())))
                            {
                                zip.ExtractAll(Server.MapPath("~/"), ExtractExistingFileAction.OverwriteSilently);
                                ViewData["resultMessage"] = "Файл разархивирован успешно";
                            }
                        }
                        catch (Exception ex)
                        {
                            ExceptionUtility.LogException(logger, ex,
                                "public ActionResult service(FormCollection formValues, string confirmButton)",
                                "Ошибка разархивирования файла");

                            ViewData["resultMessage"] = "Ошибка разархивирования";
                        }
                    }
                    else
                        ViewData["resultMessage"] = "Не загружен файл для извлечения архива. Файл должен быть в корневой директории домена";

                }

                #endregion
            }
            else if (confirmButton == "Архивировать")
            {
                #region

                string dname = formValues["dname"].ToString();
                if (dname.Trim() == "")
                {
                    ViewData["resultMessage"] = "Задайте директорию";
                }
                else
                {
                    if (System.IO.Directory.Exists(Server.MapPath("~/" + dname.Trim())))
                    {
                        try
                        {
                            using (ZipFile zip = new ZipFile()) // ZipFile.Read(Server.MapPath("~/" + dname.Trim())))
                            {
                                zip.AddDirectory(Server.MapPath("~/" + dname.Trim()), ""); //.ExtractAll(Server.MapPath("~/"), ExtractExistingFileAction.OverwriteSilently);
                                zip.Save(Server.MapPath("~/out.zip"));
                                ViewData["resultMessage"] = "Директория архивирована успешно. Файл 'out.zip' в корне сайта";
                            }
                        }
                        catch (Exception ex)
                        {
                            ExceptionUtility.LogException(logger, ex,
                                "public ActionResult service(FormCollection formValues, string confirmButton)",
                                "Ошибка архивирования директории");

                            ViewData["resultMessage"] = "Ошибка архивирования директории";
                        }
                    }
                    else
                        ViewData["resultMessage"] = "Нет такой директории";

                }

                #endregion
            }
           


            return View();
        }

        
        // разархивировать файл
        [Authorize(Roles = "Administrator")]
        [HttpPost]
        public ActionResult UploadZIP(HttpPostedFileBase image)
        {
            foreach (string upload in Request.Files)
            {
                var postedFile = Request.Files[upload];
                if (postedFile.ContentLength > 0)
                {
                    string path = AppDomain.CurrentDomain.BaseDirectory;// +"App_Data/";
                    string filename = Path.GetFileName(Request.Files[upload].FileName);
                    Request.Files[upload].SaveAs(Path.Combine(path, filename));
                    try
                    {
                        using (ZipFile zip = ZipFile.Read(Server.MapPath("~/" + filename)))
                        {
                            zip.ExtractAll(Server.MapPath("~/"), ExtractExistingFileAction.OverwriteSilently);
                            ViewData["resultMessage"] = "Файл загружен и разархивирован успешно";
                        }
                    }
                    catch (Exception ex)
                    {
                        ExceptionUtility.LogException(logger, ex,
                                "public ActionResult UploadZIP(HttpPostedFileBase image)",
                                "Ошибка разархивирования файла");

                        ViewData["resultMessage"] = "Ошибка разархивирования";
                    }
                }
            }

            return View("service");

        }

       

        #endregion

        

        

    }
}
